package cucumber.runtime.java.guice.impl;
import com.google.inject.Key;
import com.google.inject.OutOfScopeException;
import com.google.inject.Provider;
import cucumber.runtime.java.guice.ScenarioScope;
import java.util.HashMap;
import java.util.Map;
public class SequentialScenarioScope implements ScenarioScope {
/**
* Scopes a provider. The returned provider returns objects from this scope.
* If an object does not exist in this scope, the provider can use the given
* unscoped provider to retrieve one.
* <p/>
* <p>Scope implementations are strongly encouraged to override
* {@link Object#toString} in the returned provider and include the backing
* provider's {@code toString()} output.
*
* @param key binding key
* @param unscoped locates an instance when one doesn't already exist in this
* scope.
* @return a new provider which only delegates to the given unscoped provider
* when an instance of the requested object doesn't already exist in this
* scope
*/
@Override
public <T> Provider<T> scope(final Key<T> key, final Provider<T> unscoped) {
return new Provider<T>() {
public T get() {
if (scenarioValues == null) {
throw new OutOfScopeException("Cannot access " + key + " outside of a scoping block");
}
@SuppressWarnings("unchecked")
T current = (T) scenarioValues.get(key);
if (current == null && !scenarioValues.containsKey(key)) {
current = unscoped.get();
scenarioValues.put(key, current);
}
return current;
}
};
}
private Map<Key<?>, Object> scenarioValues = null;
@Override
public void enterScope() {
checkState(scenarioValues == null, "A scoping block is already in progress");
scenarioValues = new HashMap<Key<?>, Object>();
}
@Override
public void exitScope() {
checkState(scenarioValues != null, "No scoping block in progress");
scenarioValues = null;
}
private void checkState(boolean expression, String errorMessage) {
if (!expression) {
throw new IllegalStateException(errorMessage);
}
}
}